﻿Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Json
Imports System.Net
Imports System.IO

Public Class _default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Response.Write(Page.ClientQueryString)
        'For Each a In Me.ExtractQueryValues(Page.ClientQueryString)
        '    Response.Write(a.Key & " = " & a.Value)
        'Next
        'Response.End()
        Me.ExtractUri()
    End Sub


    Private Function ExtractQueryValues(ByVal QueryString As String) As Dictionary(Of String, String)
        Dim retval As New Dictionary(Of String, String)
        If QueryString <> "" Then
            Dim qstring = Split(QueryString, "&")
            For Each a In qstring
                retval.Add(Split(a, "=")(0), Split(a, "=")(1))
            Next
        End If
        Return retval
    End Function

    Dim wphonesvc As New com.apphb.wphonepusher.Service1


    Sub ExtractUri()
        If Request.HttpMethod <> "POST" Then
            'Response.StatusCode = 405
            'Response.StatusDescription = "Incorrect syntax"
            'Response.Write("You should use this in a POST to set the channel URI")
            'Response.[End]()

            For Each b In wphonesvc.GetMembers
                Response.Write("Member: " & b.AppId)
            Next


        Else


            Dim aByteReq As Byte() = New Byte(Request.ContentLength - 1) {}

            Request.InputStream.Read(aByteReq, 0, Request.ContentLength)

            Dim aStrReq As String = System.Text.UTF8Encoding.UTF8.GetString(aByteReq)

            Dim MethodeStringIndex = aStrReq.IndexOf("methode=")
            REM methodeStrings = "auth,send"

            If MethodeStringIndex <> 0 Then
                Response.Write("No MethodeString entered...")
            Else
                Dim ff = ExtractQueryValues(aStrReq)

                Select Case ff("methode")
                    Case "login"
                        Response.Write("you want to login...")

                        Me.MakeLogin(ff)
                    Case "send"
                        REM methode=send&type=tile/badge/ToastSimpleText&appid=0000
                        Dim AppType As AppSendTypes = Me.GetAppDatas(ff("appid"))
                        If AppType IsNot Nothing Then
                            If ff.ContainsKey("xml") = False Then
                                Response.Write("Sendnotifyd(true/false): " & Me.SendNotification(AppType, ff("type"), ff("text"), ""))
                            Else
                                Response.Write("Sendnotifyd(true/false): " & Me.SendNotification(AppType, ff("type"), ff("text"), "", ff("xml")))
                            End If
                        Else
                            Response.Write("you have to add the app first...")
                        End If
                    Case Else
                        Response.Write(ff("methode"))
                End Select
            End If
        End If

        Response.End()
    End Sub

    Private Sub MakeLogin(ByVal querydic As Dictionary(Of String, String))
        REM should be like this:
        REM AppId=""&sid=""&secret=""&channelUri=""

        Dim ntype As New AppSendTypes
        With ntype
            .AppId = querydic("appid")
            .ChannelUri = HttpUtility.UrlDecode(querydic("channeluri"))
            .Secret = querydic("secret")
            If querydic.ContainsKey("sid") Then
                .Sid = querydic("sid")
            End If
            .AccessToken = Me.GetAccessToken(.Sid, .Secret)
            If querydic.ContainsKey("typefor") = False Then
                .TypeFor = "both"
            Else
                .TypeFor = querydic("typefor")
            End If
        End With

        If Application("Apps") IsNot Nothing Then
            Dim applists = CType(Application("Apps"), List(Of AppSendTypes))

            applists.Add(ntype)
            Application("Apps") = applists
        Else
            Dim f As New List(Of AppSendTypes)
            f.Add(ntype)
            Application.Add("Apps", f)
        End If
    End Sub


    Function GetAppDatas(ByVal Appid As String) As AppSendTypes
        If Application("Apps") IsNot Nothing Then
            Dim applists = CType(Application("Apps"), List(Of AppSendTypes))
            '            Application("Apps") = applists
            Dim f = From a In applists
                    Where a.AppId = Appid
                    Select a

            If f.Count > 0 Then
                Return f(0)
            Else
                Return Nothing
            End If
        Else
            Return Nothing
        End If
    End Function

    Function GetOAuthTokenFromJson(ByVal jsonString As String) As OAuthToken
        Using ms As New System.IO.MemoryStream(Encoding.Unicode.GetBytes(jsonString))
            Dim ser = New DataContractJsonSerializer(GetType(OAuthToken))
            Dim oAuthToken = CType(ser.ReadObject(ms), OAuthToken)
            Return oAuthToken
        End Using
    End Function



    Private Function GetAccessToken(ByVal sids, ByVal secrets) As String

        Dim url As String = "https://login.live.com/accesstoken.srf"
        Dim request = DirectCast(WebRequest.Create(url), HttpWebRequest)
        request.ServicePoint.Expect100Continue = False
        request.Method = "POST"
        request.ContentType = "application/x-www-form-urlencoded"

        Dim sid As String = HttpUtility.UrlEncode(sids)
        Dim secret As String = HttpUtility.UrlEncode(secrets)

        Dim content As String = "grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com"

        Dim data As String = String.Format(content, sids, secrets)

        Dim notificationMessage As Byte() = Encoding.[Default].GetBytes(data)
        request.ContentLength = notificationMessage.Length

        Using requestStream As Stream = request.GetRequestStream()
            requestStream.Write(notificationMessage, 0, notificationMessage.Length)
        End Using

        Dim response = DirectCast(request.GetResponse(), HttpWebResponse)

        Dim result As String
        Using responseStream As Stream = response.GetResponseStream()
            Dim streamReader = New StreamReader(responseStream)
            result = streamReader.ReadToEnd()
        End Using
        Dim oAuthToken = GetOAuthTokenFromJson(result)
        Return oAuthToken.Token
    End Function


    Public Function SendNotification(ByVal dicentry As AppSendTypes, ByVal pushType As String, ByVal text As String, ByVal imageSource As String) As Boolean

        Dim result = False
        Select Case dicentry.TypeFor
            Case "metro"
                result = Me.SendMetroNotification(dicentry, pushType, text, imageSource)
            Case "phone"
                result = Me.SendPhoneNotifiction(dicentry, pushType, text, imageSource)
            Case "both"
                result = Me.SendMetroAndPhoneNotification(dicentry, pushType, text, imageSource)
        End Select
        Return result
    End Function


    Public Function SendMetroNotification(ByVal dicentry As AppSendTypes, ByVal pushtype As String, ByVal text As String, ByVal imagesource As String) As Boolean
        Dim result As Boolean
        Try
            Dim rawType = "wns/"
            Dim notificationContent = String.Empty

            Select Case pushtype
                Case "badge"
                    rawType += "badge"
                    notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><badge value=""{0}""/>", text)
                Case "tile"
                    rawType += "tile"
                    notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><tile><visual lang=""en-US"">                       <binding template=""TileWideSmallImageAndText03""><image id=""1"" src=""{0}""/><text id=""1"">{1}</text>                        </binding></visual></tile>", imagesource, text)
                Case "toastWithImage"
                    rawType += "toast"
                    notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><toast><visual><binding template=""ToastImageAndText01""><image id=""1"" src=""{0}"" alt=""Placeholder image""/><text id=""1"">{1}</text></binding></visual></toast>", imagesource, text)
                Case "toastsimpletext"
                    rawType += "toast"
                    Dim Simple = String.Format("<?xml version='1.0' encoding='utf-8'?><toast><visual lang=""en-US""><binding template=""ToastText01""><text id=""1"">{0}</text></binding></visual></toast>", text)
                    notificationContent = Simple
            End Select

            Response.Write(dicentry.ChannelUri.ToString)
            Dim subscritionUri As New Uri(dicentry.ChannelUri)
            '        var request = (HttpWebRequest)WebRequest.Create(subscriptionUri);
            Dim request = CType(WebRequest.Create(subscritionUri), HttpWebRequest)

            request.Method = "POST"
            request.ContentType = "text/xml"
            request.Headers = New WebHeaderCollection()
            request.Headers.Add("X-WNS-Type", rawType)
            request.Headers.Add("Authorization", "Bearer " + dicentry.AccessToken)
            '        byte[] notificationMessage = Encoding.Default.GetBytes(notificationContent);
            Dim notificationMessage = Encoding.Default.GetBytes(notificationContent)
            request.ContentLength = notificationMessage.Length

            Using requestStream = request.GetRequestStream()
                '        {
                requestStream.Write(notificationMessage, 0, notificationMessage.Length)
                '        }

                Dim resp = CType(request.GetResponse(), HttpWebResponse)
                Response.Write(resp.StatusCode)

                If resp.StatusCode = HttpStatusCode.OK Then
                    result = True
                Else
                    result = False
                End If
            End Using
        Catch e As Exception
            Response.Write(e.Message.ToString)
        End Try
        Return result
    End Function

    Public Function SendPhoneNotifiction(ByVal dicentry As AppSendTypes, ByVal pushtype As String, ByVal text As String, ByVal imagesource As String) As Boolean
        Dim result As Boolean
        Try
            ' Get the URI that the Microsoft Push Notification Service returns to the push client when creating a notification channel.
            ' Normally, a web service would listen for URIs coming from the web client and maintain a list of URIs to send
            ' notifications out to.
            Dim subscriptionUri As String = dicentry.ChannelUri


            Dim sendNotificationRequest As HttpWebRequest = DirectCast(WebRequest.Create(subscriptionUri), HttpWebRequest)

            ' Create an HTTPWebRequest that posts the raw notification to the Microsoft Push Notification Service.
            ' HTTP POST is the only method allowed to send the notification.
            sendNotificationRequest.Method = "POST"

            Dim messageString As String = ""
            Dim notificationMessage As Byte()

            ' Create the raw message.
            Select Case pushtype
                Case "phoneraw"
                    messageString = "<?xml version=""1.0"" encoding=""utf-8""?>" & "<root>" & "<Value1>" & text & "<Value1>" & "<Value2>" & "" & "<Value2>" & "</root>"
                    notificationMessage = Encoding.[Default].GetBytes(messageString)

                    sendNotificationRequest.ContentLength = notificationMessage.Length
                    sendNotificationRequest.ContentType = "text/xml"
                    sendNotificationRequest.Headers.Add("X-NotificationClass", "3")
                Case "phonetile"
                    Dim tileMessage = "<?xml version=""1.0"" encoding=""utf-8""?><wp:Notification xmlns:wp=""WPNotification""><wp:Tile Id=""Navigation Uri of the Tile to update""><wp:BackgroundImage>front side of Tile background image path</wp:BackgroundImage><wp:Count>front side of Tile count</wp:Count><wp:Title>front side of Tile title</wp:Title><wp:BackBackgroundImage>back side of Tile image path</wp:BackBackgroundImage><wp:BackTitle>back side of Tile title</wp:BackTitle><wp:BackContent>back side of Tile text</wp:BackContent></wp:Tile></wp:Notification>"
                    notificationMessage = Encoding.[Default].GetBytes(tileMessage)

                    sendNotificationRequest.ContentType = "text/xml"
                    sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token")
                    sendNotificationRequest.Headers.Add("X-NotificationClass", "1")

                Case "phonetoast"
                    Dim toastMessage As String = "<?xml version=""1.0"" encoding=""utf-8""?>" & "<wp:Notification xmlns:wp=""WPNotification"">" & "<wp:Toast>" & "<wp:Text1><string></wp:Text1>" & "<wp:Text2><string></wp:Text2>" & "<wp:Param><string></wp:Param>" & "</wp:Toast>" & "</wp:Notification>"
                    notificationMessage = Encoding.[Default].GetBytes(toastMessage)

                    sendNotificationRequest.ContentType = "text/xml"
                    sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast")
                    sendNotificationRequest.Headers.Add("X-NotificationClass", "2")
            End Select

            If notificationMessage IsNot Nothing Then
                If notificationMessage.Count > 0 Then
                    Using requestStream As Stream = sendNotificationRequest.GetRequestStream()
                        requestStream.Write(notificationMessage, 0, notificationMessage.Length)
                    End Using

                    ' Send the notification and get the response.
                    Dim resp As HttpWebResponse = DirectCast(sendNotificationRequest.GetResponse(), HttpWebResponse)
                    Dim notificationStatus As String = resp.Headers("X-NotificationStatus")
                    Dim notificationChannelStatus As String = resp.Headers("X-SubscriptionStatus")
                    Dim deviceConnectionStatus As String = resp.Headers("X-DeviceConnectionStatus")

                    ' Display the response from the Microsoft Push Notification Service.  
                    ' Normally, error handling code would be here. In the real world, because data connections are not always available,
                    ' notifications may need to be throttled back if the device cannot be reached.
                    Response.Write("phone: " & notificationStatus & " | " & deviceConnectionStatus & " | " & notificationChannelStatus)
                    If resp.StatusCode = HttpStatusCode.OK Then
                        result = True
                    Else
                        result = False
                    End If
                Else
                    result = False
                    Response.Write("no notification bytes generated...")
                End If
            Else
                result = False
                Response.Write("no notification bytes set...")
            End If
        Catch ex As Exception
            Response.Write("Exception caught sending update: " & ex.ToString())
        End Try
        Return result
    End Function

    Public Function SendMetroAndPhoneNotification(ByVal dicentry As AppSendTypes, ByVal pushtype As String, ByVal text As String, ByVal imagesource As String) As Boolean
        Dim a = Me.SendMetroNotification(dicentry, pushtype, text, imagesource)
        If a = True Then
            Response.Write("Both: Metro succeeded")
        Else
            Response.Write("Both: Metro not succeeded")
        End If
        Dim b = Me.SendPhoneNotifiction(dicentry, pushtype, text, imagesource)
        If b = True Then
            Response.Write("Both: Phone succeeded")
        Else
            Response.Write("Both: Phone not succeeded")
        End If
        If a = True And b = True Then
            Return True
        Else
            Return False
        End If
    End Function

    'Protected Sub ButtonSendRaw_Click(sender As Object, e As EventArgs)
    '    Try
    '        ' Get the URI that the Microsoft Push Notification Service returns to the push client when creating a notification channel.
    '        ' Normally, a web service would listen for URIs coming from the web client and maintain a list of URIs to send
    '        ' notifications out to.
    '        Dim subscriptionUri As String = TextBoxUri.Text.ToString()


    '        Dim sendNotificationRequest As HttpWebRequest = DirectCast(WebRequest.Create(subscriptionUri), HttpWebRequest)

    '        ' Create an HTTPWebRequest that posts the raw notification to the Microsoft Push Notification Service.
    '        ' HTTP POST is the only method allowed to send the notification.
    '        sendNotificationRequest.Method = "POST"

    '        ' Create the raw message.
    '        Dim rawMessage As String = "<?xml version=""1.0"" encoding=""utf-8""?>" & "<root>" & "<Value1>" & TextBoxValue1.Text.ToString() & "<Value1>" & "<Value2>" & TextBoxValue2.Text.ToString() & "<Value2>" & "</root>"

    '        ' Set the notification payload to send.
    '        Dim notificationMessage As Byte() = Encoding.[Default].GetBytes(rawMessage)

    '        ' Set the web request content length.
    '        sendNotificationRequest.ContentLength = notificationMessage.Length
    '        sendNotificationRequest.ContentType = "text/xml"
    '        sendNotificationRequest.Headers.Add("X-NotificationClass", "3")


    '        Using requestStream As Stream = sendNotificationRequest.GetRequestStream()
    '            requestStream.Write(notificationMessage, 0, notificationMessage.Length)
    '        End Using

    '        ' Send the notification and get the response.
    '        Dim response As HttpWebResponse = DirectCast(sendNotificationRequest.GetResponse(), HttpWebResponse)
    '        Dim notificationStatus As String = response.Headers("X-NotificationStatus")
    '        Dim notificationChannelStatus As String = response.Headers("X-SubscriptionStatus")
    '        Dim deviceConnectionStatus As String = response.Headers("X-DeviceConnectionStatus")

    '        ' Display the response from the Microsoft Push Notification Service.  
    '        ' Normally, error handling code would be here. In the real world, because data connections are not always available,
    '        ' notifications may need to be throttled back if the device cannot be reached.
    '        TextBoxResponse.Text = notificationStatus & " | " & deviceConnectionStatus & " | " & notificationChannelStatus
    '    Catch ex As Exception
    '        TextBoxResponse.Text = "Exception caught sending update: " & ex.ToString()
    '    End Try

    'End Sub


    Public Function SendNotification(ByVal dicentry As AppSendTypes, ByVal pushType As String, ByVal text As String, ByVal imageSource As String, ByVal xmlcontent As String) As Boolean

        Dim result = False

        Try

            Dim rawType = "wns/"
            Dim notificationContent = String.Empty

            Select Case pushType
                Case "badge"
                    rawType += "badge"
                    '       notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><badge value=""{0}""/>", text)
                Case "tile"
                    rawType += "tile"
                    '      notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><tile><visual lang=""en-US"">                       <binding template=""TileWideSmallImageAndText03""><image id=""1"" src=""{0}""/><text id=""1"">{1}</text>                        </binding></visual></tile>", imageSource, text)
                Case "toastWithImage"
                    rawType += "toast"
                    '     notificationContent = String.Format("<?xml version='1.0' encoding='utf-8'?><toast><visual><binding template=""ToastImageAndText01""><image id=""1"" src=""{0}"" alt=""Placeholder image""/><text id=""1"">{1}</text></binding></visual></toast>", imageSource, text)
                Case "toastsimpletext"
                    rawType += "toast"
                    Dim Simple = String.Format("<?xml version='1.0' encoding='utf-8'?><toast><visual lang=""en-US""><binding template=""ToastText01""><text id=""1"">{0}</text></binding></visual></toast>", text)
                    '    notificationContent = Simple
            End Select

            notificationContent = xmlcontent

            Dim subscritionUri As New Uri(HttpUtility.UrlDecode(dicentry.ChannelUri))
            '        var request = (HttpWebRequest)WebRequest.Create(subscriptionUri);
            Dim request = CType(WebRequest.Create(subscritionUri), HttpWebRequest)

            request.Method = "POST"
            request.ContentType = "text/xml"
            request.Headers = New WebHeaderCollection()
            request.Headers.Add("X-WNS-Type", rawType)
            request.Headers.Add("Authorization", "Bearer " + dicentry.AccessToken)
            '        byte[] notificationMessage = Encoding.Default.GetBytes(notificationContent);
            Dim notificationMessage = Encoding.Default.GetBytes(notificationContent)
            request.ContentLength = notificationMessage.Length

            Using requestStream = request.GetRequestStream()
                '        {
                requestStream.Write(notificationMessage, 0, notificationMessage.Length)
                '        }

                Dim resp = CType(request.GetResponse(), HttpWebResponse)
                Response.Write(resp.StatusCode)

                If resp.StatusCode = HttpStatusCode.OK Then
                    result = True
                Else
                    result = False
                End If
            End Using
        Catch e As Exception
            Response.Write(e.Message.ToString)

        End Try
        Return result
    End Function

  

End Class

Public Class AppSendTypes
    Property AppId As String
    Property Secret As String
    Property Sid As String
    Property ChannelUri As String
    Property AccessToken As String
    Property TypeFor As String REM phone,metro,both
End Class

<System.Runtime.Serialization.DataContract>
Public Class OAuthToken
    <DataMember(Name:="access_token")>
    Public Property Token As String
    <DataMember(Name:="token_type")>
    Public TokenType As String
End Class
